using System;
using System.Collections.Generic;

namespace Is
{
    public abstract class ContainsEnumerableBase<T, TIs> : IsBase<TIs, IEnumerable<T>> where TIs : ContainsEnumerableBase<T, TIs>
    {
        protected ContainsEnumerableBase(IEnumerable<T> target, bool negate) : base(target, negate) { }

        public bool Any(Func<T, bool> predicate)
        {
            return ((IIs<IEnumerable<T>>)this).Apply(
                t => Core.Is.Contains(t, predicate),
                t => Core.Is.NotContains(t, predicate));
        }

        public bool One(Func<T, bool> predicate)
        {
            return ((IIs<IEnumerable<T>>)this).Apply(
                t => Core.Is.ContainsExactly(t, predicate, 1),
                t => !Core.Is.ContainsExactly(t, predicate, 1));
        }

        public bool One(T value)
        {
            return ((IIs<IEnumerable<T>>)this).Apply(
                t => Core.Is.ContainsExactly(t, value, 1),
                t => !Core.Is.ContainsExactly(t, value, 1));
        }

        public bool Item(T item)
        {
            return ((IIs<IEnumerable<T>>)this).Apply(
                t => Core.Is.Contains(t, item),
                t => Core.Is.NotContains(t, item));
        }

        public bool Exactly(int expectedCount)
        {
            return ((IIs<IEnumerable<T>>)this).Apply(
                t => Core.Is.ContainsExactly(t, expectedCount),
                t => !Core.Is.ContainsExactly(t, expectedCount));
        }

        public bool AtLeast(int expectedMinimumCount)
        {
            return ((IIs<IEnumerable<T>>)this).Apply(
                t => Core.Is.ContainsAtLeast(t, expectedMinimumCount),
                t => !Core.Is.ContainsAtLeast(t, expectedMinimumCount));
        }

        public bool NoMoreThan(int expectedMaximumCount)
        {
            return ((IIs<IEnumerable<T>>)this).Apply(
                t => Core.Is.ContainsNoMoreThan(t, expectedMaximumCount),
                t => !Core.Is.ContainsNoMoreThan(t, expectedMaximumCount));
        }

        public bool Zero()
        {
            return Exactly(0);
        }

        public bool One()
        {
            return Exactly(1);
        }
    }
}